package fgin

import (
	"encoding/base64"
	"errors"
	"fmt"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

func checkAuthConfig() error {
	if fginConfig.Auth.SecreKey == "" {
		return errors.New("auth密钥没有配置")
	}
	if fginConfig.Auth.Timeout == 0 {
		return errors.New("auth过期时间没配置")
	}
	if fginConfig.Auth.HeaderKey == "" {
		return errors.New("auth鉴权的header_key没有配置")
	}
	return nil
}

type customClaims struct {
	jwt.RegisteredClaims
	AuthData map[string]string
}

func GenToken(authData map[string]string) (string, error) {
	resToken := ""
	if err := checkAuthConfig(); err != nil {
		return resToken, err
	}
	for _, v := range fginConfig.Auth.AuthLs {
		_, ok := authData[v]
		if !ok {
			errInfo := fmt.Sprintf("配置了%v参数,但是没有传入", v)
			return resToken, errors.New(errInfo)
		}
	}
	// 增加jwt携带配置
	claims := customClaims{
		AuthData: authData,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(fginConfig.Auth.Timeout) * time.Second)), //过期时间
			IssuedAt:  jwt.NewNumericDate(time.Now()),                                                           //签发时间
		},
	}
	var token *jwt.Token
	switch fginConfig.Auth.SigningMethod {
	case 1:
		token = jwt.NewWithClaims(jwt.SigningMethodHS384, claims)
	case 2:
		token = jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
	default:
		token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	}
	if strToken, err := token.SignedString([]byte(fginConfig.Auth.SecreKey)); err != nil {
		return resToken, err
	} else {
		resToken = strToken
	}
	// token使用base64遮掩一下
	enResToken := base64.StdEncoding.EncodeToString([]byte(resToken))
	return enResToken, nil
}

func ParsearseToken(tokenStr string) (*customClaims, error) {
	// 解密一下token base64
	tokenB, err := base64.StdEncoding.DecodeString(tokenStr)
	if err != nil {
		return nil, err
	}
	tokenStr = string(tokenB)
	// 设置框架jwt能使用的算法
	parser := jwt.NewParser(
		jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Name, jwt.SigningMethodHS384.Name, jwt.SigningMethodHS512.Name}),
	)
	token, err := parser.ParseWithClaims(tokenStr, &customClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(fginConfig.Auth.SecreKey), nil //返回签名密钥
	})
	if err != nil {
		return nil, err
	}

	if !token.Valid {
		return nil, errors.New("令牌过期")
	}

	claims, ok := token.Claims.(*customClaims)
	if !ok {
		return nil, errors.New("反序列化失败")
	}

	return claims, nil
}
